package com.ssb.util.sign;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.*;

/**
 * @author: Don
 * @date: 2018/9/6 12:11
 * @description: 签名工具
 */
public class SignUtil {
    private static final String ENCODING = "gbk";

    /**
     * Discription 获取签名串
     * @author Don
     * @date 2018/9/6 17:20
     * @param
     * @return
     */
    public static String getWebapiToSignData(Map<String, String> data, String secretKey)
    {
        StringBuilder sb = new StringBuilder();
        Set<String> keySet = data.keySet();
        List<String> keyList = new ArrayList<>();
        keyList.addAll(keySet);
        Collections.sort(keyList);
        for (String s : keyList) {
            //Signature字段不参与运算
            if ("Signature".equals(s)) {
                continue;
            }
            String val = data.get(s);
            //空值不参与运算
            if (val != null && !"".equals(val)) {
                sb.append(val).append("_");
            }
        }
        sb.append(secretKey);
        return sb.toString();
    }

    /**
     * Discription 获取签名串
     * @author Don
     * @date 2018/9/6 17:20
     * @param
     * @return
     */
    public static String getWebapiToSignDataFromMap(Map<String, Object> data, String secretKey)
    {
        StringBuilder sb = new StringBuilder();
        Set<String> keySet = data.keySet();
        List<String> keyList = new ArrayList<>();
        keyList.addAll(keySet);
        //将所有请求字段名称按ASCII码从小到大排序
        Collections.sort(keyList);
        for (String s : keyList) {
            //Signature字段不参与运算
            if ("Signature".equals(s)) {
                continue;
            }
            Object obj = data.get(s);
            //空值不参与运算
            if (obj != null) {
                if (obj instanceof String) {
                    if (!"".equals(obj)) {
                        sb.append(obj).append("_");
                    }
                } else if (obj instanceof Map) {
                    getWebapiToSignDataFromMap((Map<String, Object>) obj, secretKey);
                } else if (obj instanceof List) {
                    List<?> listObj = (List<?>) obj;
                    for (Object o : listObj) {
                        getWebapiToSignDataFromMap((Map<String, Object>) o, secretKey);
                    }
                } else {
                    sb.append(String.valueOf(obj)).append("_");
                }
            }
        }
        sb.append(secretKey);
        return  sb.toString();
    }

    /**
     * Discription webapi签名
     * @author Don
     * @date 2018/9/6 17:06
     * @param
     * @return
     */
    public static String sign(RSAHelper helper, String sourceString) throws UnsupportedEncodingException,
                                                                      NoSuchAlgorithmException,
                                                                      InvalidKeyException, SignatureException
    {
        //GBK 编码
        byte[] sourceBytes = sourceString.getBytes(ENCODING);
        //md5 摘要
        String md5Hex = DigestHelper.getMD5HexString(sourceBytes);
        //GBK 编码
        byte[] toSignBytes = md5Hex.getBytes(ENCODING);
        //签名
        byte[] signBytes = helper.sign(toSignBytes);
        String signResult = Base64Helper.encode(signBytes);
        return signResult;
    }

    /**
     * Discription webapi验签
     * @author Don
     * @date 2018/9/7 11:13
     * @param
     * @return
     */
    public static boolean verifySign(RSAHelper helper, String sourceString, byte[] verifyCode) throws InvalidKeyException, SignatureException, NoSuchAlgorithmException, UnsupportedEncodingException
    {
        //GBK 编码
        byte[] sourceBytes = sourceString.getBytes(ENCODING);
        //md5 摘要
        String md5Hex = DigestHelper.getMD5HexString(sourceBytes);
        //GBK 编码
        byte[] toSignBytes = md5Hex.getBytes(ENCODING);
        //验签
        return helper.verifySign(toSignBytes, verifyCode);
    }
}
